<template>
  <div class="role">
    <hzhy-data-table ref="dataTable" v-bind="tableConfig">
      <template slot="left-btn">
        <el-button type="primary" icon="el-icon-plus" plain @click="handleRowUpdate('add')">
          添加
        </el-button>
      </template>
    </hzhy-data-table>
    <common-drawer-form
      ref="commonDrawerForm"
      :visible.sync="visible"
      :title="drawerTitle"
      :content="formContent"
      :onConfirm="onConfirm"
    ></common-drawer-form>
    <permission-config-drawer
      :visible.sync="configVisible"
      :list="dataList"
      :selected="dataSelected"
      :loading="configLoading"
      :confim="handleConfigConfirm"
    >
    </permission-config-drawer>
    <role-view-drawer
      v-if="roleViewVisible"
      :visible.sync="roleViewVisible"
      :roleViewUrl="roleViewUrl"
      :roleId="roleId"
      :curTenantId="curTenantId"
    >
    </role-view-drawer>
  </div>
</template>

<script>
import CommonDrawerForm from '@/components/common-drawer-form'
import PermissionConfigDrawer from '@/container/system/permission-config-drawer'
import RoleViewDrawer from '@/container/system/role/role-view-drawer'
import * as api from '@/const/api'

export default {
  title: '角色管理',
  name: 'SystemRole',
  components: {
    CommonDrawerForm,
    PermissionConfigDrawer,
    RoleViewDrawer,
  },
  data() {
    return {
      roleViewVisible: false,
      roleViewUrl: '',
      tableConfig: {
        url: api.sysRolePage,
        columns: [
          {
            label: '序号',
            type: 'index',
            prop: 'index',
            fixed: 'left',
          },
          {
            label: '角色名称',
            prop: 'name',
          },
          {
            label: 'code',
            prop: 'code',
          },
          {
            label: '是否启用',
            prop: 'valid',
            formatter: ({ valid }) => (valid === 1 ? '启用' : '禁用'),
          },
          {
            label: '操作',
            prop: 'operation',
            width: 280,
            fixed: 'right',
            setBtns: (row) => {
              const btns = [
                {
                  label: '编辑',
                  handler: () => {
                    this.handleRowUpdate('edit', row)
                  },
                },
                {
                  label: '删除',
                  className: 'red',
                  handler: () => {
                    this.handleRowDelete(row)
                  },
                },
                {
                  label: '分配资源',
                  handler: () => {
                    this.handleConfigRole(row)
                  },
                },
                {
                  label: '角色人员查看',
                  className: '',
                  handler: () => {
                    this.handleRowView(row)
                  },
                },
              ]
              return this.$ac.operationAccess(btns)
            },
          },
        ],
        searchForm: [
          {
            $type: 'input',
            $id: 'name',
            label: '角色名称',
            $el: {
              clearable: true,
              placeholder: '请输入',
            },
          },
        ],
      },
      formContent: [
        {
          $id: 'name',
          $type: 'input',
          label: '角色名称',
          $el: {
            placeholder: '请输入角色名称',
            clearable: true,
            maxLength: 11,
          },
          rules: [{ required: true, message: '请输入角色名称', trigger: 'change' }],
        },
        {
          $id: 'code',
          $type: 'input',
          label: '角色code',
          $el: {
            placeholder: '请输入角色code',
            clearable: true,
            maxlength: 20,
            showWordLimit: true,
          },
          rules: [{ required: true, message: '请输入角色code', trigger: 'change' }],
        },
        {
          $id: 'valid',
          $type: 'switch',
          label: '启用标志',
          $el: {
            activeValue: 1,
            inactiveValue: 0,
          },
        },
      ],
      roleId: null,
      curTenantId: null, // 用于角色人员查看所属机构传参
      visible: false,
      configVisible: false,
      currentRow: {}, // 当前编辑项
      dataList: [], // 菜单数据
      dataSelected: [], // 菜单已勾选
      configLoading: false, // 数据加载标识
    }
  },
  computed: {
    // 编辑还是新增
    isEdit() {
      return !!this.currentRow.id
    },
    // 侧边栏表单标题
    drawerTitle() {
      return this.isEdit ? '编辑' : '新增'
    },
  },
  methods: {
    // 侧边栏form确认回调
    async onConfirm(data) {
      try {
        const params = {
          ...data,
        }
        // 编辑需要加上id参数
        if (this.isEdit) {
          params.id = this.currentRow.id
        }

        let res = ''

        if (this.isEdit) {
          res = await this.$axios.$put(api.sysRole, params)
        } else {
          res = await this.$axios.$post(api.sysRole, params)
        }

        const { code, msg } = res
        if (+code !== 200) {
          throw new Error(msg || '操作失败')
        }

        this.$message.success('操作成功')
        this.$refs.dataTable.goPage() // 刷新界面
      } catch (err) {
        this.$message.error(err.message)
      }
    },
    // 打开侧边栏form弹层
    handleRowUpdate(type, row) {
      this.visible = true
      if (type === 'edit') {
        this.currentRow = row
        this.$refs.commonDrawerForm.updateForm(row)
      } else {
        this.currentRow = {}
      }
    },
    async handleRowDelete(row) {
      let loading = ''
      try {
        const isFlag = await this.$confirm('确认删除？', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning',
        })
        if (isFlag !== 'confirm') {
          return
        }
        loading = this.$loading({
          text: 'Loading',
          spinner: 'el-icon-loading',
        })
        const { code, msg } = await this.$axios.$delete(api.sysRole, {
          params: {
            id: row.id,
          },
        })
        if (+code !== 200) {
          throw new Error(msg || '操作失败')
        }
        this.$message.success('操作成功')
        this.$refs.dataTable.goPage() // 刷新界面
      } catch (err) {
        err.message && this.$message.error(err.message)
      } finally {
        loading && loading.close()
      }
    },
    async handleConfigRole(row) {
      this.dataList = []
      this.dataSelected = []
      this.currentRow = row
      this.configVisible = true
      try {
        const allAjax = []

        // 获取所有可用资源列表
        allAjax.push(this.$axios.$get(api.sysAppList))
        // 获取当前角色已勾选数据
        allAjax.push(this.$axios.$get(api.getSysRoleMenu(row.id)))

        this.configLoading = true
        const res = await Promise.all(allAjax)

        let flag = ''
        // 判断请求是否请求成功
        res.forEach(({ code, msg }) => {
          if (+code !== 200) {
            flag = msg || '操作失败'
          }
        })
        if (flag) {
          throw new Error(flag)
        }

        const [dataList, dataSelected] = res

        // 所有可用数据
        this.dataList = dataList.data

        // 重新组装list数据,查看当前菜单是否有子级
        const listWrapper = {}

        this.dataList.forEach((item) => {
          const flag = this.dataList.filter((v) => v.parentId === item.id).length
          listWrapper[item.id] = !flag
        })

        // 当前角色勾选，需过滤父级id，只保留所有子级id，不然显示会有问题 。可能会有性能问题，2层for循环
        const appIds = []

        dataSelected.data.forEach((item) => {
          listWrapper[item.id] && appIds.push(item.id)
        })
        this.dataSelected = appIds
      } catch (err) {
        this.$message.error(err.message)
      } finally {
        this.configLoading = false
      }
    },
    // 角色人员查看
    async handleRowView(row) {
      this.roleId = row.id
      this.curTenantId = row.tenantId
      this.roleViewVisible = true
      this.roleViewUrl = api.sysRoleUsers(row.id)
    },
    async handleConfigConfirm(data) {
      try {
        const params = {
          roleId: this.currentRow.id,
          menuIds: data.map(({ id }) => id),
        }
        const { code, msg } = await this.$axios.$post(api.roleMenuRelation, params)
        if (+code !== 200) {
          throw new Error(msg || '操作失败')
        }
        this.$message.success('操作成功')
      } catch (err) {
        err.message && this.$message.error(err.message)
      }
    },
  },
}
</script>
<style lang="less" scoped>
.index {
  position: relative;
  width: calc(100vw - 106px);
  height: calc(100vh - 154px);
  background-color: #fff;
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center center;
}
</style>
